﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.IO;
using MMOShared;
using System.Reflection;

namespace MMOResCreator
{
    public partial class ResourceListForm : Form
    {
        private UInt16 CurrentVersion;
        private MasterVersionList Versions;

        public ResourceListForm()
        {
            InitializeComponent();
            Versions = new MasterVersionList();
            this.chVerDD.SelectedIndexChanged += new EventHandler(chVerDD_SelectedIndexChanged);
            this.resL.OnResourceEntryUpdated += new MMOCustomControls.EditableListView.ResourceEntryUpdated(resL_OnResourceEntryUpdated);
        }

        void resL_OnResourceEntryUpdated(int index, ResourceEntry updatedEntry)
        {
            Versions.GetVersion(CurrentVersion).UpdateResource(index, updatedEntry);
        }

        void chVerDD_SelectedIndexChanged(object sender, EventArgs e)
        {
            CurrentVersion = (UInt16)(chVerDD.SelectedIndex+1);
            ChangeVersion(CurrentVersion);
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {

        }

        private void addResB_ButtonClick(object sender, EventArgs e)
        {
            OpenFileDialog add = new OpenFileDialog();
            if (add.ShowDialog() == DialogResult.OK)
            {
                add.Multiselect = false;
                add.AddExtension = true;

                string fullpath = add.FileName;
                string match = "\\Updates\\" + CurrentVersion + "\\";

                int o = fullpath.IndexOf(match);

                if (o == -1)
                {
                    MessageBox.Show("Error: you can only add files from an update version directory (\\Updates\\#\\) to a resource file");
                    return;
                }

                string relPath = fullpath.Substring(o + match.Length, fullpath.Length - o - match.Length);
                string contPath = relPath.Substring(0, relPath.IndexOf("."));

                string chkSum = "";
                using (HashAlgorithm hashAlg = new SHA1Managed())
                {
                    using (Stream file = new FileStream(fullpath, FileMode.Open, FileAccess.Read))
                    {
                        byte[] hash = hashAlg.ComputeHash(file);
                        chkSum = BitConverter.ToString(hash);
                    }
                }
                FileInfo f = new FileInfo(fullpath);
                string name = f.Name.Substring(0, f.Name.IndexOf("."));
                this.resL.AddNewItem(name, relPath, contPath, chkSum, fullpath);
            }
        }

        private void delResB_ButtonClick(object sender, EventArgs e)
        {
            ListView.SelectedIndexCollection col = this.resL.SelectedIndices;
            for (int i = col.Count - 1; i >= 0; i--)
            {
                this.resL.Items.RemoveAt(col[i]);
            }
        }

        private void scanMI_Click(object sender, EventArgs e)
        {
            Versions.ScanDirectory("Updates\\");

            UInt16[] vers = Versions.GetLoadedVersionNumbers();
            this.chVerDD.Items.Clear();
            if (vers.Length > 0)
            {
                foreach (UInt16 v in vers)
                {
                    this.chVerDD.Items.Add(v);
                }
                this.chVerDD.Enabled = true;
            }

            ChangeVersion(Versions.LatestVersion);

            if (CurrentVersion > 0)
            {
                addResB.Enabled = true;
                delResB.Enabled = true;
            }
            else
            {
                statusL.Text = "No Versions Loaded";
            }
        }

        private void ChangeVersion(UInt16 ver)
        {
            this.chVerDD.SelectedItem = ver;

            CurrentVersion = ver;
            ResourceManager res = Versions.GetVersion(CurrentVersion);
            if (res != null)
            {
                this.resL.SetResourceItems(res.Resources,"Updates\\"+ver+"\\");
                this.statusL.Text = "Current Version: " + CurrentVersion;
            }

            if (ver > 0)
            {
                chVerDD.Enabled = true;
                addResB.Enabled = true;
                delResB.Enabled = true;
            }
        }

        private void newVerMI_Click(object sender, EventArgs e)
        {
            ResourceManager res = new ResourceManager((UInt16)(CurrentVersion+1));
            
            string path = "Updates\\" + (CurrentVersion + 1).ToString() + "\\";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            CurrentVersion++;
            ScanDirToAdd(path, res);

            this.chVerDD.Items.Add(CurrentVersion);
            Versions.AddNewVersion(res);
            ChangeVersion((UInt16)(CurrentVersion));
        }

        private void ScanDirToAdd(string dir,ResourceManager res){
            DirectoryInfo di = new DirectoryInfo(dir);
            FileInfo[] files = di.GetFiles();
            foreach (FileInfo fi in files)
            {
                ResourceEntry r = BuildEntryFromFile(fi.FullName);
                res.AddResource(r);

            }
            DirectoryInfo[] dirs = di.GetDirectories();
            foreach (DirectoryInfo d in dirs)
            {
                if (d.Name[0] != '.')
                {
                    ScanDirToAdd(d.FullName, res);
                }
            }
        }

        private ResourceEntry BuildEntryFromFile(string path)
        {
            string match = "Updates\\" + CurrentVersion + "\\";

            int o = path.IndexOf(match);
            if (o == -1)
            {
                MessageBox.Show("Error: you can only add files from an update version directory (\\Updates\\#\\) to a resource file. Current file path, "+path);
                return null;
            }

            string relPath = path.Substring(o + match.Length, path.Length - o - match.Length);
            string contPath = relPath.Substring(0, relPath.IndexOf("."));

            string chkSum = "";
            using (HashAlgorithm hashAlg = new SHA1Managed())
            {
                using (Stream file = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    byte[] hash = hashAlg.ComputeHash(file);
                    chkSum = BitConverter.ToString(hash);
                }
            }
            FileInfo f = new FileInfo(path);
            string name = f.Name.Substring(0,f.Name.IndexOf("."));
            return new ResourceEntry(relPath, contPath, name, chkSum,CompileOptions.NO_COMPILE);
        }

        private void saveVerMI_Click(object sender, EventArgs e)
        {
            ResourceManager res = Versions.GetVersion(CurrentVersion);
            if (res != null)
            {
                if (!res.Save("Updates\\res_man_" + CurrentVersion + ".res"))
                    MessageBox.Show("Error: Couldn't save resource manager");
            }
        }

        private void FinVerMI_Click(object sender, EventArgs e)
        {
            FinalizeVersionForm vf = new FinalizeVersionForm(Versions);
            vf.ShowDialog();
        }

        private void compileContentMI_Click(object sender, EventArgs e)
        {
            ResourceManager curV = Versions.GetVersion(CurrentVersion);
            List<ResourceEntry> compItems = new List<ResourceEntry>();
            foreach (ListViewItem i in resL.Items)
            {
                if (i.Checked)
                {
                    int idx = i.Index;
                    compItems.Add(curV.Resources[idx]);
                }
            }
            CompileContentForm f = new CompileContentForm(compItems,CurrentVersion);
            f.ShowDialog();
        }

        private void checkAB_ButtonClick(object sender, EventArgs e)
        {
            foreach (ListViewItem i in resL.Items)
            {
                i.Checked = true;
            }
        }

        private void uncheckAB_ButtonClick(object sender, EventArgs e)
        {
            foreach (ListViewItem i in resL.Items)
            {
                i.Checked = false;
            }
        }

        private void exitMI_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
